package netcom;

import java.io.*;
import java.nio.charset.Charset;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import nu.xom.*;
import pimp.ApplicationError;
import pimp.organizermanager.*;
import pimp.organizermanager.Node;

public class DBManager
{
    private CalendarGroup calendarGroup;
    String user = "user";
    String pass = "pass";

    private DBManager()
    {
        System.out.println("DBManager initialization completed!");
    }

    private static class Singleton
    {
        private final static DBManager instance = new DBManager();
    }

    public static DBManager getInstance()
    {
        return Singleton.instance;
    }

    public Document modelToDoc(TreeModel model)
    {
        Object root = model.getRoot();

        Element el = getSubTree(model,root,0);
        Document doc = new Document(el);
        return doc;
    }

    public TreeModel docToModel(Document doc)
    {
        Node root = null;

        Element docRoot = doc.getRootElement();
        root = new Node(docRoot.getLocalName());
        addLevelToNode(docRoot.getChildElements(), root);
        return new DefaultTreeModel(root);
    }
    public void addLevelToNode(Elements level, Node node)
    {
        int size = level.size();
        for(int i = 0; i < size; ++i)
        {
            node.addChild(new Node(level.get(i).getLocalName()));
            addLevelToNode(level.get(i).getChildElements(),node.getLastChild());
        }
    }

    public Element getSubTree(TreeModel model, Object node, int depth)
    {
        Element el = new Element(node.toString());
        //for(int i=0; i<depth; i++) System.out.print("* ");
        //System.out.print(node.toString());

        int n = model.getChildCount(node);
        if(n==0)
            el.appendChild(((pimp.organizermanager.Node)node).getValue());

        //System.out.println(" = " + Integer.toString(n));
        for(int i=0; i<n ; i++ )
           el.appendChild( getSubTree(model, model.getChild(node, i),depth+1) );

        return el;
    }

    public void saveDataBaseToFile()
    {
        System.out.println("void DBManager::saveDataBaseToFile()");

        calendarGroup = CalendarGroup.getInstance();

        Document doc = modelToDoc(calendarGroup.getLabelTreeModel());
        
        String path = "";
        try
        {
            path = new java.io.File(".").getCanonicalPath();
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        File tmp = new File(path + "\\save\\");
        tmp.mkdir();
        path = path + "\\save\\data.xml";
        System.out.println("Saving to: " + path);
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(path);
        }
        catch (FileNotFoundException ex)
        {
            ApplicationError.showError("File not found: " + ex);
            System.out.println("File not found: " + ex);
        }
        try
        {
            Serializer serializer = new Serializer(fos, "Windows-1250");
            serializer.setIndent(4);
            serializer.setMaxLength(64);
            serializer.write(doc);
            serializer.flush();
        }
        catch(IOException ex)
        {
            System.err.println(ex);
        }
        try
        {
            fos.close();
        }
        catch (IOException ex)
        {
            ApplicationError.showError("Could not close file");
            System.out.println("Could not close file");
        }
    }

    public void saveDataBaseToServer()
    {
        System.out.println("void DBManager::saveDataBaseToServer()");
        Client c = new Client(user,pass,"localhost",5000);
        if(c.connect())
        {
            calendarGroup = CalendarGroup.getInstance();
            Document doc = modelToDoc(calendarGroup.getLabelTreeModel());
            c.saveData(doc.toXML());
            c.close();
        }
        else
        {
            c.close();
        }
    }

    public TreeModel getDataBaseFromFile()
    {
        String path = null;
        try
        {
            path = new java.io.File(".").getCanonicalPath();
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        path = path + "\\save\\data.xml";
        File tmp = new File(path);
        Builder builder = new Builder();
        Document doc = null;
        try
        {
            doc = builder.build(tmp);
        }
        catch (ParsingException ex)
        {
            ApplicationError.showError("Could not parse file");
            System.out.println("Could not parse file");
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        ////////////// test !
        /*TreeModel newModel = docToModel(doc);
        Document newDoc = modelToDoc(newModel);
        try
        {
            path = new java.io.File(".").getCanonicalPath();
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        path = path + "\\save\\reading_from_file.xml";
        System.out.println("Saving to: " + path);
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(path);
        }
        catch (FileNotFoundException ex)
        {
            System.out.println("File I/O error: " + ex);
        }
        try
        {
            Serializer serializer = new Serializer(fos, "Windows-1250");
            serializer.setIndent(4);
            serializer.setMaxLength(64);
            serializer.write(doc);
            serializer.flush();
        }
        catch(IOException ex)
        {
            System.err.println(ex);
        }
        try
        {
            fos.close();
        }
        catch (IOException ex)
        {
            System.out.println("Could not close file");
        }
        *///////////////
        return docToModel(doc);
    }

    public TreeModel getDataBaseFromServer()
    {
        System.out.println("void DBManager::getDataBaseFromServer()");
        Client c = new Client(user,pass,"localhost",5000);
        c.connect();
        String file = c.getData();
        c.close();
        file = new String(file.getBytes(Charset.forName("UTF-8")));
        String path = "";
        try
        {
            path = new java.io.File(".").getCanonicalPath();
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        File tmp = new File(path + "\\save\\");
        tmp.mkdir();
        try
        {
            tmp = File.createTempFile("TMP", null, tmp);
        }
        catch (IOException ex)
        {
            ApplicationError.showError("Could not create temp file, could not load data...");
            System.out.println("Could not create temp file, could not load data...");
            return null;
        }
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(tmp);
        }
        catch (FileNotFoundException ex)
        {
            ApplicationError.showError("File not found: " + ex);
            System.out.println("File not found: " + ex);
        }
        try
        {
            fos.write(file.getBytes());
        }
        catch (IOException ex)
        {
            ApplicationError.showError("Could not write to temp file, could not parse data");
            System.out.println("Could not write to temp file, could not parse data");
            return null;
        }
        try
        {
            fos.close();
        }
        catch (IOException ex)
        {
            ApplicationError.showError("Could not close temp file");
            System.out.println("Could not close temp file");
            return null;
        }
        Builder builder = new Builder();
        Document doc = null;
        try
        {
            doc = builder.build(tmp);
        }
        catch (ParsingException ex)
        {
            ApplicationError.showError("Could not parse file");
            System.out.println("Could not parse file");
            System.out.println(ex);
        }
        catch (IOException ex)
        {
            ApplicationError.showError("Could not build document");
            System.out.println("Could not build document");
        }
        tmp.deleteOnExit();
        ////////////// test !
        /*TreeModel newModel = docToModel(doc);
        Document newDoc = modelToDoc(newModel);
        try
        {
            path = new java.io.File(".").getCanonicalPath();
        }
        catch (IOException ex)
        {
            System.out.println(ex);
        }
        path = path + "\\save\\reading_from_server.xml";
        System.out.println("Saving to: " + path);
        try
        {
            fos = new FileOutputStream(path);
        }
        catch (FileNotFoundException ex)
        {
            System.out.println("File I/O error: " + ex);
        }
        try
        {
            Serializer serializer = new Serializer(fos, "Windows-1250");
            serializer.setIndent(4);
            serializer.setMaxLength(64);
            serializer.write(doc);
            serializer.flush();
        }
        catch(IOException ex)
        {
            System.err.println(ex);
        }
        try
        {
            fos.close();
        }
        catch (IOException ex)
        {
            System.out.println("Could not close file");
        }
        *///////////////
        return docToModel(doc);
    }
}
